using System;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using Crainiate.Data.Persistence.Cache;

namespace Crainiate.Data.Persistence.Providers
{
    public abstract class Formatter
    {
        //Working variables
        private Dictionary<Type, Dictionary<object, IPersistable>> mDictionaries;

        //Properties
        public abstract Command Command { get; set;}
        public abstract Concurrency Concurrency { get; set;}

        //Methods
        public abstract void Encode(IPersistable graph, Type type);
        public abstract void Decode(IPersistable graph, Type type);

        public virtual IPersistable ActivateObject(Type type, object key)
        {
            if (mDictionaries == null) mDictionaries = new Dictionary<Type, Dictionary<object, IPersistable>>();
            Dictionary<object, IPersistable> objects;

            //Check for dictionary of this type
            if (!mDictionaries.TryGetValue(type, out objects))
            {
                objects = new Dictionary<object, IPersistable>();
                mDictionaries.Add(type, objects);
            }

            //Check type for this key
            IPersistable persistable = null;
            if (objects.TryGetValue(key, out persistable))
            {
                return persistable;
            }
            else
            {
                persistable = Command.Context.CreatePersistable(type);

                //Set up concurrency
                persistable.Concurrency = Command.Context.CreateConcurrency();

                objects.Add(key, persistable);

                return persistable;
            }
        }

        public virtual void Reset()
        {
            if (mDictionaries != null) mDictionaries.Clear();
        }

        public static string GetPropertyName(PropertyInfo prop, string seperator)
        {
            string propname = prop.Name;

            //Add the key name to the property name if an IPersistable object
            if (typeof(IPersistable).IsAssignableFrom(prop.PropertyType))
            {
                ReflectionCacheItem propcache = Component.Instance.ReflectionCache.Lookup(prop.PropertyType);
                propname += seperator + GetPropertyName(propcache.PrimaryKey, "");
            }
            return propname;
        }
    }
}
